package proxy.gui;

import java.awt.BorderLayout;
import java.awt.CardLayout;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.GridLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.BorderFactory;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.DefaultListModel;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JMenuItem;
import javax.swing.JPanel;
import javax.swing.JPasswordField;
import javax.swing.JPopupMenu;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JTextField;
import javax.swing.JTree;
import javax.swing.SwingUtilities;
import javax.swing.event.TreeSelectionEvent;
import javax.swing.event.TreeSelectionListener;
import javax.swing.table.DefaultTableModel;

import proxy.Configure;
import proxy.model.User;

public class DialogConfigure extends JDialog{

	private static final long serialVersionUID = 911082347099876014L;
	
	private static final String GENERAL_TAB = "General";
	private static final String USER_TAB = "User";
	private static final String CACHE_TAB = "Cache";
	private static final String BLOCK_SITE_TAB = "Block Site";
	private JTree tree;
	private CardLayout cards;
	private JPanel panelCards;
	private ActionListener cancel;
	
	// User tab
	JTable tableUser;
	DefaultTableModel modelUser;
	JTextField txtUsername;
	JPasswordField txtPassword;
	JButton buttonAddUser;
	JButton buttonDeleteUser;
	String[] columns = new String[]{"No.", "Username", "Password"};
	
	//General tab
	JTextField txtHost;
	JTextField txtPort;
	JTextField txtProxyForwardHost;
	JTextField txtProxyForwardPort;
	JCheckBox chkForwardProxy;
	
	public DialogConfigure(){
		setSize(600, 400);
		setDefaultCloseOperation(JFrame.HIDE_ON_CLOSE);
		setTitle("Configure...");
		setModal(true);
		setResizable(false);
		
		Container container = getContentPane();
		cards = new CardLayout();
		panelCards = new JPanel(cards);
		cancel = new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				setVisible(false);
			}
		};
		panelCards.add(createGeneralTab(), GENERAL_TAB);
		panelCards.add(createUserTab(), USER_TAB);
		panelCards.add(createCacheTab(), CACHE_TAB);
		panelCards.add(createBlockSiteTab(), BLOCK_SITE_TAB);
		tree = new JTree(new String[]{GENERAL_TAB, USER_TAB, BLOCK_SITE_TAB});
		Dimension dimension = tree.getPreferredSize();
		dimension.width = 200;
		tree.setPreferredSize(dimension);
		tree.setLargeModel(true);
		tree.setRowHeight(25);
		tree.setFocusable(false);
		tree.addTreeSelectionListener(new TreeSelectionListener() {
			@Override
			public void valueChanged(TreeSelectionEvent e) {
				cards.show(panelCards, e.getNewLeadSelectionPath().getLastPathComponent().toString());
			}
		});
		BorderLayout layout = new BorderLayout(5, 0);
		container.setLayout(layout);
		container.add(panelCards, BorderLayout.CENTER);
		container.add(tree, BorderLayout.WEST);
	}
	
	private JPanel createGeneralTab(){
		JPanel panelSetup = new JPanel();
		panelSetup.setLayout(new GridBagLayout());
		
		GridBagConstraints c = new GridBagConstraints();
		panelSetup.setBorder(BorderFactory.createTitledBorder("Setup"));
		c.fill = GridBagConstraints.HORIZONTAL;
		c.gridx = 0;
		c.gridy = 0;
		panelSetup.add(new JLabel("Bind to:"), c);
		c.gridx = 1;
		c.insets = new Insets(0, 5, 0, 0);
		panelSetup.add(txtHost = new JTextField(Configure.getInstance().host, 20), c);
		c.gridx = 2;
		panelSetup.add(new JLabel("Port"), c);
		c.gridx = 3;
		panelSetup.add(txtPort = new JTextField(String.valueOf(Configure.getInstance().port), 5), c);
		
		JPanel networkProxy = new JPanel();
		networkProxy.setLayout(new GridBagLayout());
		networkProxy.setBorder(BorderFactory.createTitledBorder("Network proxy"));
		c.insets = new Insets(0, 0, 0, 0);
		c.gridx = 0;
		c.gridy = 0;
		c.gridwidth = 4;
		final JCheckBox useNetworkProxy = new JCheckBox("Use network proxy");
		useNetworkProxy.setSelected(Configure.getInstance().useForwardProxy);
		networkProxy.add(useNetworkProxy, c);
		c.gridx = 0;
		c.gridy = 1;
		c.gridwidth = 1;
		networkProxy.add(new JLabel("Host"), c);
		c.gridx = 1;
		c.insets = new Insets(0, 5, 0, 0);
		final JTextField txtProxyForward = new JTextField(Configure.getInstance().proxyForwardHost, 20);
		networkProxy.add(txtProxyForward, c);
		c.gridx = 2;
		networkProxy.add(new JLabel("Port"), c);
		c.gridx = 3;
		final JTextField txtPortForward = new JTextField(String.valueOf(Configure.getInstance().proxyForwardPort), 5);
		networkProxy.add(txtPortForward, c);

		JPanel root = new JPanel(new GridBagLayout());
		root.add(panelSetup);
		c.insets = new Insets(0, 0, 0, 0);
		c.gridx = 0;
		c.gridy = 0;
		c.weightx = 1;
		c.fill = GridBagConstraints.FIRST_LINE_START;
		c.anchor = GridBagConstraints.FIRST_LINE_START;
		root.add(panelSetup, c);
		c.gridy = 1;
		useNetworkProxy.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent arg0) {
				txtPortForward.setEnabled(useNetworkProxy.isSelected());
				txtProxyForward.setEnabled(useNetworkProxy.isSelected());
			}
		});
		useNetworkProxy.setSelected(Configure.getInstance().useForwardProxy);
		txtPortForward.setEnabled(Configure.getInstance().useForwardProxy);
		txtProxyForward.setEnabled(Configure.getInstance().useForwardProxy);
		root.add(networkProxy, c);
		ActionListener ok = new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				Configure.getInstance().useForwardProxy = useNetworkProxy.isSelected();
				Configure.getInstance().proxyForwardHost = txtProxyForward.getText();
				Configure.getInstance().proxyForwardPort = Integer.parseInt(txtPortForward.getText());
				Configure.getInstance().port = Integer.parseInt(txtPort.getText());
				Configure.getInstance().host = txtHost.getText();
			}
		};
		JPanel panel = createPanelButton(ok);
		panel.add(root, BorderLayout.NORTH);
		return panel;
	}
	
	private JPanel createUserTab(){
		final JPanel panelAddUser = new JPanel();
		JPanel both = new JPanel();
		both.setLayout(new GridLayout(2, 1, 5, 5));
		final JCheckBox useAccount = new JCheckBox("Use account");
		useAccount.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent arg0) {
				txtUsername.setEnabled(useAccount.isSelected());
				txtPassword.setEnabled(useAccount.isSelected());
				tableUser.setEnabled(useAccount.isSelected());
				buttonAddUser.setEnabled(useAccount.isSelected());
			}
		});
		useAccount.setSelected(Configure.getInstance().authenticated);
		both.add(useAccount);
		panelAddUser.setBorder(BorderFactory.createEmptyBorder(0, 0, 5, 0));
		panelAddUser.setLayout(new BoxLayout(panelAddUser, BoxLayout.X_AXIS));
		panelAddUser.add(new JLabel("Username:"));
		panelAddUser.add(Box.createHorizontalStrut(5));
		panelAddUser.add(txtUsername = new JTextField(10));
		panelAddUser.add(Box.createHorizontalStrut(5));
		panelAddUser.add(new JLabel("Password:"));
		panelAddUser.add(Box.createHorizontalStrut(5));
		panelAddUser.add(txtPassword = new JPasswordField(10));
		panelAddUser.add(Box.createHorizontalStrut(5));
		panelAddUser.add(buttonAddUser = new JButton("Add"));
		buttonAddUser.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent arg0) {
				if (txtUsername.getText().equals("") || txtPassword.getPassword().length == 0) return;
				final User user = new User(txtUsername.getText(), new String(txtPassword.getPassword()));
				if (Configure.getInstance().users.contains(user)) return;
				Configure.getInstance().users.add(user);
				SwingUtilities.invokeLater(new Runnable() {
					public void run() {
						modelUser.addRow(new String[]{String.valueOf(Configure.getInstance().users.size()), user.username, user.password.replaceAll("[^*]", "*")});
					}
				});
			}
		});
		
		JPanel tab = new JPanel();
		tab.setLayout(new BorderLayout(5, 5));
		tableUser = new JTable(){
			private static final long serialVersionUID = -1866396254930976935L;
			@Override
			public boolean isCellEditable(int arg0, int arg1) {
				return false;
			}
		};
		tableUser.setModel(modelUser = new DefaultTableModel(columns, 0));
		tableUser.setRowHeight(25);
		tableUser.setFocusable(false);
		tableUser.setShowHorizontalLines(true);
		tableUser.setShowVerticalLines(false);
		tableUser.setFillsViewportHeight(true);
		tableUser.getColumnModel().getColumn(0).setMaxWidth(50);
		txtUsername.setEnabled(Configure.getInstance().authenticated);
		txtPassword.setEnabled(Configure.getInstance().authenticated);
		tableUser.setEnabled(Configure.getInstance().authenticated);
		buttonAddUser.setEnabled(Configure.getInstance().authenticated);
		JPopupMenu popup = new JPopupMenu();
		JMenuItem delete = new JMenuItem("Delete");
		delete.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent arg0) {
				final int[] indies = tableUser.getSelectedRows();
				SwingUtilities.invokeLater(new Runnable() {
					public void run() {
						for (int i = indies.length - 1; i >= 0; i--) {
							Configure.getInstance().users.remove(indies[i]);
							modelUser.removeRow(indies[i]);
						}
					}
				});
			}
		});
		popup.add(delete);
		tableUser.setComponentPopupMenu(popup);
		tab.add(new JScrollPane(tableUser, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED), BorderLayout.CENTER);
		SwingUtilities.invokeLater(new Runnable() {
			public void run() {
				for (int i = 0; i < Configure.getInstance().users.size(); i++){
					User user = Configure.getInstance().users.get(i);
					modelUser.addRow(new String[]{String.valueOf(i + 1), user.username, user.password.replaceAll("[^*]", "*")});
				}
			}
		});
		ActionListener ok = new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				Configure.getInstance().authenticated = useAccount.isSelected();
			}
		};
		JPanel panel = createPanelButton(ok);
		both.add(panelAddUser);
		panel.add(both, BorderLayout.NORTH);
		panel.add(new JScrollPane(tableUser, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED), BorderLayout.CENTER);
		return panel;
	}
	
	private JPanel createCacheTab(){
		ActionListener ok = new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				
			}
		};
		JPanel panel = createPanelButton(ok);
		panel.add(new JLabel("Cache"), BorderLayout.CENTER);
		return panel;
	}
	
	private JPanel createBlockSiteTab(){
		final JList sites = new JList();
		final JCheckBox useBlockSite = new JCheckBox("Use site block");
		JPanel both = new JPanel(new GridLayout(2, 1, 5, 5));
		useBlockSite.setSelected(Configure.getInstance().useBlockSite);
		final DefaultListModel modelSites = new DefaultListModel();
		sites.setModel(modelSites);
		sites.setFixedCellHeight(25);
		SwingUtilities.invokeLater(new Runnable() {
			@Override
			public void run() {
				for (String site : Configure.getInstance().blockSites){
					modelSites.addElement(site);
				}
			}
		});
		
		JPopupMenu popup = new JPopupMenu();
		JMenuItem delete = new JMenuItem("Delete");
		delete.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent arg0) {
				final int[] indies = sites.getSelectedIndices();
				SwingUtilities.invokeLater(new Runnable() {
					public void run() {
						for (int i = indies.length - 1; i >= 0; i--) {
							Configure.getInstance().blockSites.remove(indies[i]);
							modelSites.remove(indies[i]);
						}
					}
				});
			}
		});
		popup.add(delete);
		sites.setComponentPopupMenu(popup);
		final JTextField txtSite;
		final JButton buttonAddSite;
		JPanel panelAddSites = new JPanel();
		panelAddSites.setBorder(BorderFactory.createEmptyBorder(0, 0, 5, 0));
		panelAddSites.setLayout(new BoxLayout(panelAddSites, BoxLayout.X_AXIS));
		panelAddSites.add(new JLabel("Site : "));
		panelAddSites.add(Box.createHorizontalStrut(5));
		panelAddSites.add(txtSite = new JTextField(10));
		panelAddSites.add(Box.createHorizontalStrut(5));
		panelAddSites.add(buttonAddSite = new JButton("Add"));
		buttonAddSite.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent arg0) {
				SwingUtilities.invokeLater(new Runnable() {
					public void run() {
						String site = txtSite.getText();
						if (site.equals("") || Configure.getInstance().blockSites.contains(site)) return;
						Configure.getInstance().blockSites.add(site);
						modelSites.addElement(site);
					}
				});
			}
		});
		
		ActionListener ok = new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				Configure.getInstance().useBlockSite = useBlockSite.isSelected();
			}
		};
		useBlockSite.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent arg0) {
				txtSite.setEnabled(useBlockSite.isSelected());
				buttonAddSite.setEnabled(useBlockSite.isSelected());
			}
		});
		txtSite.setEnabled(useBlockSite.isSelected());
		buttonAddSite.setEnabled(useBlockSite.isSelected());
		JPanel panel = createPanelButton(ok);
		both.add(useBlockSite);
		both.add(panelAddSites);
		panel.add(both, BorderLayout.NORTH);
		panel.add(new JScrollPane(sites, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED), BorderLayout.CENTER);
		return panel;
	}
	
	private JPanel createPanelButton(ActionListener ok){
		JPanel root = new JPanel();
		root.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
		root.setLayout(new BorderLayout());
		JPanel button = new JPanel();
		button.setBorder(BorderFactory.createEmptyBorder(5 , 0, 0, 0));
		button.setLayout(new BoxLayout(button, BoxLayout.X_AXIS));
		JButton buttonOK = new JButton("Apply");
		buttonOK.addActionListener(ok);
		JButton buttonCancel = new JButton("Close");
		buttonCancel.addActionListener(cancel);
		button.add(Box.createHorizontalGlue());
		button.add(buttonOK);
		button.add(Box.createHorizontalStrut(5));
		button.add(buttonCancel);
		root.add(button, BorderLayout.SOUTH);
		return root;
	}
}
